package com.gui.spring.aop.springProxy;

import cn.hutool.core.util.RandomUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

public class SpringAdviceDemo {

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("logAspect", LogAspect.class);
        context.registerBean("aopService", AopService.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.registerBean("config", Config.class);
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
        context.refresh();
        System.out.println("==========================================");
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        AopService aopService = context.getBean("aopService", AopService.class);
        System.out.println(aopService.getClass());
        System.out.println("===========================================");
        aopService.foo("hahahahh");
    }

    @Component
    static class AopService {
        public String foo(String text) {
            System.out.println("foo....");
            return RandomUtil.randomString(6);
        }
    }

    @Aspect
    static class LogAspect {

        @Before("execution(* foo(..))")
        @Order(1111)
        public void before() {
            System.out.println("LogAspect before...");
        }

        @Before("execution(* foo(..))")
        @Order(222)
        public void before1() {
            System.out.println("LogAspect before1...");
        }


        @After("execution(* foo(..))")
        public void after() {
            System.out.println("LogAspect after...");
        }

    }

    @Configuration
    static class Config{

        @Bean
        public MethodInterceptor methodInterceptor1(){
            return invocation -> {
                System.out.println("前置增强，打印参数..." + Arrays.toString(invocation.getArguments()));
                Object result = invocation.proceed();
                System.out.println("后置增强，打印返回值..." + result);
                return result;
            };
        }

        @Bean
        public Advisor advisor(MethodInterceptor methodInterceptor1){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo(..))");
            return new DefaultPointcutAdvisor(pointcut, methodInterceptor1);
        }

    }
}
